#!/usr/bin/env node

var test = require('tape');
var bufferEqual = require('buffer-equal');
var WebSocketFrame = require('../../lib/WebSocketFrame');
var utils = require('../../lib/utils');
var bufferAllocUnsafe = utils.bufferAllocUnsafe;
var bufferFromString = utils.bufferFromString;


test('Serializing a WebSocket Frame with no data', function(t) {
  t.plan(2);
  
  // WebSocketFrame uses a per-connection buffer for the mask bytes
  // and the frame header to avoid allocating tons of small chunks of RAM.
  var maskBytesBuffer = bufferAllocUnsafe(4);
  var frameHeaderBuffer = bufferAllocUnsafe(10);
  
  var frameBytes;
  var frame = new WebSocketFrame(maskBytesBuffer, frameHeaderBuffer, {});
  frame.fin = true;
  frame.mask = true;
  frame.opcode = 0x09; // WebSocketFrame.PING
  t.doesNotThrow(
    function() { frameBytes = frame.toBuffer(true); },
    'should not throw an error'
  );
  
  t.assert(
    bufferEqual
      (frameBytes, bufferFromString('898000000000', 'hex')),
    'Generated bytes should be correct'
  );
  
  t.end();
});

test('Serializing a WebSocket Frame with 16-bit length payload', function(t) {
  t.plan(2);

  var maskBytesBuffer = bufferAllocUnsafe(4);
  var frameHeaderBuffer = bufferAllocUnsafe(10);

  var payload = bufferAllocUnsafe(200);
  for (var i = 0; i < payload.length; i++) {
    payload[i] = i % 256;
  }

  var frameBytes;
  var frame = new WebSocketFrame(maskBytesBuffer, frameHeaderBuffer, {});
  frame.fin = true;
  frame.mask = true;
  frame.opcode = 0x02; // WebSocketFrame.BINARY
  frame.binaryPayload = payload;
  t.doesNotThrow(
    function() { frameBytes = frame.toBuffer(true); },
    'should not throw an error'
  );

  var expected = bufferAllocUnsafe(2 + 2 + 4 + payload.length);
  expected[0] = 0x82;
  expected[1] = 0xFE;
  expected.writeUInt16BE(payload.length, 2);
  expected.writeUInt32BE(0, 4);
  payload.copy(expected, 8);

  t.assert(
    bufferEqual(frameBytes, expected),
    'Generated bytes should be correct'
  );

  t.end();
});

test('Serializing a WebSocket Frame with 64-bit length payload', function(t) {
  t.plan(2);

  var maskBytesBuffer = bufferAllocUnsafe(4);
  var frameHeaderBuffer = bufferAllocUnsafe(10);

  var payload = bufferAllocUnsafe(66000);
  for (var i = 0; i < payload.length; i++) {
    payload[i] = i % 256;
  }

  var frameBytes;
  var frame = new WebSocketFrame(maskBytesBuffer, frameHeaderBuffer, {});
  frame.fin = true;
  frame.mask = true;
  frame.opcode = 0x02; // WebSocketFrame.BINARY
  frame.binaryPayload = payload;
  t.doesNotThrow(
    function() { frameBytes = frame.toBuffer(true); },
    'should not throw an error'
  );

  var expected = bufferAllocUnsafe(2 + 8 + 4 + payload.length);
  expected[0] = 0x82;
  expected[1] = 0xFF;
  expected.writeUInt32BE(0, 2);
  expected.writeUInt32BE(payload.length, 6);
  expected.writeUInt32BE(0, 10);
  payload.copy(expected, 14);

  t.assert(
    bufferEqual(frameBytes, expected),
    'Generated bytes should be correct'
  );

  t.end();
});
